/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package expertos;

import DTOs.DTOProveedor;
import entidadesNegocio.CuentaCorrienteProveedor;
import entidadesNegocio.DetalleListaMateriales;
import entidadesNegocio.ListaMateriales;
import entidadesNegocio.Material;
import entidadesNegocio.Proveedor;
import excepciones.ExpertoProveedoresException;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import persistencia.ExcepcionFachada;
import persistencia.Fachada;

/**
 *
 * @author diego
 */
public class ExpertoProveedores extends Experto {

    private Proveedor proveedorSeleccionado;
    private ListaMateriales listaSeleccionada;

    public Proveedor getProveedorSeleccionado() {
        return proveedorSeleccionado;
    }

    public void setProveedorSeleccionado(Proveedor proveedorSeleccionado) {
        this.proveedorSeleccionado = proveedorSeleccionado;
        listaSeleccionada = buscarulListamaterialesProvSelecc();
    }

    public ListaMateriales getListaSeleccionada() {
        return listaSeleccionada;
    }

    public void setListaSeleccionada(ListaMateriales listaSeleccionada) {
        this.listaSeleccionada = listaSeleccionada;
    }

    public List<Proveedor> buscarProveedores(DTOProveedor dtoBusqueda) throws ExpertoProveedoresException {
        List<Proveedor> proveedores = null;
        Criteria criterio = Fachada.getInstancia().crearCriterio(Proveedor.class);
        if (dtoBusqueda.getCodigo().length() > 0) {
            criterio.add(Restrictions.like("codigoProveedor", "%" + dtoBusqueda.getCodigo() + "%"));
        }
        if (dtoBusqueda.getNombre().length() > 0) {
            criterio.add(Restrictions.like("nombre", "%" + dtoBusqueda.getNombre() + "%").ignoreCase());
        }
        if (dtoBusqueda.getTelefono().length() > 0) {
            criterio.add(Restrictions.eq("telefono", dtoBusqueda.getTelefono()));
        }
        proveedores = Fachada.getInstancia().buscar(Proveedor.class, criterio);
        if (proveedores.isEmpty()) {
            throw new ExpertoProveedoresException("No se encontraron proveedores para los datos ingresados");
        }
        return proveedores;
    }

    public List<ListaMateriales> buscarListaMaterialesProveedor(Proveedor proveedor) {
        List<ListaMateriales> listasMateriales = null;

        Criteria criterio = Fachada.getInstancia().crearCriterio(ListaMateriales.class);
        criterio.createAlias("proveedor", "prov");
        criterio.add(Restrictions.eq("prov.id", proveedor.getId()));
        criterio.addOrder(Order.asc("id"));

        listasMateriales = Fachada.getInstancia().buscar(ListaMateriales.class, criterio);


        return listasMateriales;

    }

    public List<ListaMateriales> buscarListaMaterialesProveedorSeleccionado() {
        List<ListaMateriales> listasMateriales = null;

        Criteria criterio = Fachada.getInstancia().crearCriterio(ListaMateriales.class);
        criterio.createAlias("proveedor", "prov");
        criterio.add(Restrictions.eq("prov.id", proveedorSeleccionado.getId()));
        criterio.addOrder(Order.desc("fechaInicioListaMateriales"));

        listasMateriales = Fachada.getInstancia().buscar(ListaMateriales.class, criterio);


        return listasMateriales;

    }

    public ListaMateriales buscarulListamaterialesProvSelecc() {
        if (proveedorSeleccionado == null) {
            return null;
        }
        List<ListaMateriales> listasMateriales = buscarListaMaterialesProveedor(proveedorSeleccionado);
        if (listasMateriales.isEmpty()) {
            return null;
        } else {
            for (ListaMateriales listaMateriales : listasMateriales) {
                if (listaMateriales.getFechafinlistamateriales() == null) {
                    return listaMateriales;
                }
            }
            return null;
        }
    }

    /**
     * agrega un nuevo material a la lista seleccionada
     * @param material 
     */
    public void agregarMaterialListaSeleccinada(Material material) {
        listaSeleccionada.addMaterial(material);
    }

    public void quitarMaterialListaSeleccionada(Material material) {
        listaSeleccionada.removeMaterial(material);
    }

    public void clearProveedor() {
        proveedorSeleccionado = null;
    }

    public void crearProveedor(DTOProveedor dtoDatos) {
        proveedorSeleccionado = null;
        proveedorSeleccionado = new Proveedor();
        proveedorSeleccionado.setCodigoProveedor(dtoDatos.getCodigo());
        proveedorSeleccionado.setDireccion(dtoDatos.getDireccion());
        proveedorSeleccionado.setTelefono(dtoDatos.getTelefono());
        proveedorSeleccionado.setNombre(dtoDatos.getNombre());
    }

    public void modificarProveedorSeleccionado(DTOProveedor dtoDatos) {
        proveedorSeleccionado.setCodigoProveedor(dtoDatos.getCodigo());
        proveedorSeleccionado.setDireccion(dtoDatos.getDireccion());
        proveedorSeleccionado.setTelefono(dtoDatos.getTelefono());
        proveedorSeleccionado.setNombre(dtoDatos.getNombre());
    }

    public void guardarProveedor() throws ExpertoProveedoresException {
        String validarProveedorMensaje = validarProveedor(proveedorSeleccionado);
        boolean isNuevoProveedor = false;//se usa despues para saber si debo crear o no la lista de materiales del proveedor
        if (validarProveedorMensaje != null) {
            throw new ExpertoProveedoresException(validarProveedorMensaje);
        }
        if (proveedorSeleccionado.getId() == null) {
            isNuevoProveedor = true;
        }
        try {
            Fachada.getInstancia().guardar(proveedorSeleccionado);
        } catch (Exception ex) {
            throw new ExpertoProveedoresException("ERROR al Guardar Proveedor: ");
        }
        if (isNuevoProveedor) {
            try {
                generarListaMateriales(proveedorSeleccionado);
                generarCuentaCorriente(proveedorSeleccionado);
            } catch (Exception ex) {
                System.out.println("Error al genear lista de materiales o cuenta corriente proveedor");
            }
        }
    }

    public void eliminarProveedorSeleccionado() throws ExpertoProveedoresException {
        proveedorSeleccionado.setEliminado(Boolean.TRUE);
        try {
            Fachada.getInstancia().guardar(proveedorSeleccionado);
        } catch (Exception e) {
            throw new ExpertoProveedoresException("ERROR al Eliminar Proveedor");
        }
    }

    /**
     * Regresa un string con el mensaje de error
     * si regresa null el proveedor es valido
     * @param nuevoProveedor
     * @return 
     */
    private String validarProveedor(Proveedor nuevoProveedor) {
        if (nuevoProveedor.getCodigoProveedor().length() == 0) {
            return "Código Proveedor Inválido";
        } else if (nuevoProveedor.getNombre().length() == 0) {
            return "Nombre Proveedor Inválido";
        }
        return null;
    }

    private void generarListaMateriales(Proveedor nuevoProveedor) throws Exception {
        ListaMateriales nuevaListamateriales = new ListaMateriales();
        //TODO: crear metodo getFechaActual en la fachada
        nuevaListamateriales.setFechainiciolistamateriales(new Date());
        nuevaListamateriales.setFechaModificacion(new Date());
        nuevaListamateriales.setProveedor(nuevoProveedor);

        try {
            Fachada.getInstancia().guardar(nuevaListamateriales);
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * Crea una nueva lista de materiales para el proveedor seleccionado
     * @param listaParaCopiar: esta lista se le envia para que genere una copia de ella. Si se envia null, se genera una nueva
     */
    public void crearNuevaListaMaterialesProveedorSeleccionado(ListaMateriales listaParaCopiar) throws ExpertoProveedoresException {

        ListaMateriales ultimaLista = buscarulListamaterialesProvSelecc();
        
        if (ultimaLista != null) {//se da fin a la lista seleccionada
            //TODO: crear metodo en la fachada para consultar fecha servidor
            listaSeleccionada.setFechafinlistamateriales(new Date());
            this.guardarListaMateriales(listaSeleccionada);
        }

        listaSeleccionada = new ListaMateriales();
        listaSeleccionada.setProveedor(proveedorSeleccionado);
        //TODO:crear metodo en la fachada para recuperar hora servidor
        listaSeleccionada.setFechainiciolistamateriales(new Date());
        if (listaParaCopiar != null) {
            for (DetalleListaMateriales detalleListaMateriales : listaParaCopiar.getDetallelistamaterialesList()) {
                DetalleListaMateriales nuevoDetalle = new DetalleListaMateriales();
                nuevoDetalle.setMaterial(detalleListaMateriales.getMaterial());
                nuevoDetalle.setMontoDetalle(detalleListaMateriales.getMontoDetalle());
                nuevoDetalle.setDescripcion(detalleListaMateriales.getDescripcion());
                listaSeleccionada.getDetallelistamaterialesList().add(nuevoDetalle);
            }
        }
        this.guardarListaMateriales(listaSeleccionada);
    }

    private void generarCuentaCorriente(Proveedor nuevoProveedor) throws Exception {
        CuentaCorrienteProveedor nuevaCuentaCorriente = new CuentaCorrienteProveedor();
        nuevaCuentaCorriente.setProveedor(nuevoProveedor);

        try {
            Fachada.getInstancia().guardar(nuevaCuentaCorriente);
        } catch (Exception e) {
            throw e;
        }

    }

    public void guardarListaMateriales(ListaMateriales lista) throws ExpertoProveedoresException {
        //TODO: buscar fecha en la fachada
        lista.setFechaModificacion(new Date());
        try {
            Fachada.getInstancia().guardar(lista);
        } catch (ExcepcionFachada ex) {
            throw new ExpertoProveedoresException("Error al guardar lista de materiales:\n"+ex.getMessage());
        }
    }

    public void eliminarLista(ListaMateriales lista) throws ExpertoProveedoresException {
        if (lista == null) {
            return;
        }
        lista.setEliminado(Boolean.TRUE);
        guardarListaMateriales(lista);
    }
}
